//
//  MK_BarrageManager.m
//  miku直播
//
//  Created by 杨尚达 on 2017/7/21.
//  Copyright © 2017年 杨尚达. All rights reserved.
//

#import "MK_BarrageManager.h"
#import <GCDAsyncSocket.h>
#import "MK_BarrageManagerPacketModel.h"
#import "MK_BarrageModel.h"
#import "MK_UserLogInMessageModel.h"



///socket链接IP地址
#define BARAGE_IP @"openbarrage.douyutv.com"
///端口号
#define BARAGE_PORT 8601

///socket的tag值
typedef NS_ENUM(NSUInteger, MK_BarrageManagerTagType) {
    MK_BarrageManagerTagTypeSendLength,     ///发送长度
    MK_BarrageManagerTagTypeSendData,       ///发送内容
    MK_BarrageManagerTagTypeReceiveLength,  ///接受长度
    MK_BarrageManagerTagTypeReceiveData,    ///接受内容
};


@interface MK_BarrageManager () <GCDAsyncSocketDelegate>

///socket对象
@property(nonatomic,strong)GCDAsyncSocket* socket;

///当前链接的房间号
@property(nonatomic,strong)NSString* roomNum;

///计时对象(心跳包)
@property(nonatomic,strong)dispatch_source_t timer;

@end

@implementation MK_BarrageManager

+(instancetype)share{
    static id instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [MK_BarrageManager new];
    });
    return instance;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        _socket = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];
    }
    return self;
}

///登陆指定房间号
-(void)logInRoomWith:(NSString*)roomNumBer{
    _roomNum = roomNumBer;
    [self.socket connectToHost:BARAGE_IP onPort:BARAGE_PORT error:nil];
}

-(void)logoutRoom{
    [self MK_sendLevePacket];
}


#pragma mark 发包业务
///发包方法
-(void)MK_SendPacketWithContentStr:(NSString*)contentStr{
    MK_BarrageManagerPacketModel* model = [MK_BarrageManagerPacketModel new];
    model.type = MK_BarrageManagerPacketModelType_Send;
    model.contentStr = contentStr;
    [self.socket writeData:[model getRawData] withTimeout:-1 tag:MK_BarrageManagerTagTypeSendData];
}

///发登陆包
-(void)MK_SendLogInPacket{
    [self MK_SendPacketWithContentStr:[NSString stringWithFormat:@"type@=loginreq/roomid@=%@/",self.roomNum]];
}
///发加入分组的包
-(void)MK_sendInRoom{
    [self MK_SendPacketWithContentStr:[NSString stringWithFormat:@"type@=joingroup/rid@=%@/gid@=-9999/",self.roomNum]];
}

///发送离开房间的包
-(void)MK_sendLevePacket{
    [self MK_SendPacketWithContentStr:[NSString stringWithFormat:@"type@=logout/"]];
}

///心跳包
-(void)MK_SendKeepLivePacket{
    _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
    dispatch_source_set_timer(_timer, DISPATCH_TIME_NOW, 45 * NSEC_PER_SEC, 1 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(_timer, ^{
        [self MK_SendPacketWithContentStr:[NSString stringWithFormat:@"type@=keeplive/tick@=%ld/",    (long int)[[NSDate new] timeIntervalSince1970]]];
    });
    dispatch_resume(_timer);
}
#pragma mark GCDSocket代理方法
///完成链接
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{
    NSLog(@"完成弹幕系统链接");
    [self MK_SendLogInPacket];
    [self MK_sendInRoom];
    [self MK_SendKeepLivePacket];
    [self.socket readDataToLength:4 withTimeout:-1 tag:MK_BarrageManagerTagTypeReceiveLength];
    
}
///链接失败
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(nullable NSError *)err{
    NSLog(@"链接失败%@",err);
}


-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
    ///接受循环
    switch (tag) {
        case MK_BarrageManagerTagTypeReceiveLength:{
            unsigned int length;
            [data getBytes:&length length:4];
            [self.socket readDataToLength:length withTimeout:-1 tag:MK_BarrageManagerTagTypeReceiveData];
        }
            break;
        case MK_BarrageManagerTagTypeReceiveData:{
            //    NSLog(@"获取数据");
            MK_BarrageManagerPacketModel* model = [MK_BarrageManagerPacketModel MK_BarrageManagerPacketModelWithRawData:data];
            [self MK_getModelWithDic:[self decodeStringToDic:model.contentStr]];
            [self.socket readDataToLength:4 withTimeout:-1 tag:MK_BarrageManagerTagTypeReceiveLength];
        }
            break;
    }
}

#pragma mark 获取数据转模型
///获取数据转模型 与 发通知
-(void)MK_getModelWithDic:(NSDictionary*)dic{
    NSString* type = dic[@"type"];
    if ([type isEqualToString:@"chatmsg"]) {
        MK_BarrageModel* model = [MK_BarrageModel new];
        [model setValuesForKeysWithDictionary:dic];
        [[NSNotificationCenter defaultCenter]postNotificationName:NotificationOfMK_BarrageModelSend object:model];
    }
    if ([type isEqualToString:@"uenter"]) {
        MK_UserLogInMessageModel* model = [MK_UserLogInMessageModel new];
        [model setValuesForKeysWithDictionary:dic];
        [[NSNotificationCenter defaultCenter]postNotificationName:NotificationOfMK_UseLogInRoom object:model];
    }
    if ([type isEqualToString:@"keeplive"]) {
        NSLog(@"心跳包");
    }
    
}

#pragma mark 序列化与反序列化方法
///将响应的字符串内容转换为字典
-(NSMutableDictionary*)decodeStringToDic:(NSString*)str{
    
    NSMutableDictionary<NSString*,NSString*>* resdic = [NSMutableDictionary new];
    NSArray<NSString*>* kvArr = [str componentsSeparatedByString:@"/"];
    
    [kvArr enumerateObjectsUsingBlock:^(NSString*  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSArray<NSString*>* resArr = [obj componentsSeparatedByString:@"@="];
        if (resArr.count == 2) {
            resdic[resArr.firstObject] = resArr.lastObject;
        }
    }];
    return resdic;
}

@end
